package org.apache.sad.core.framework.jaxrpc.handler;

import javax.xml.namespace.QName;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sad.core.framework.jaxrpc.ServiceContext;
import org.apache.sad.core.framework.utils.DateUtils;
import org.apache.sad.core.framework.constants.ServiceConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import org.apache.log4j.MDC;
import org.slf4j.MDC;

public class BaseSoapHandler extends GenericHandler implements ServiceConstants {
	private Logger logger = LoggerFactory.getLogger(BaseSoapHandler.class);
	
	//private static Log logger = LogFactory.getLog(BaseSoapHandler.class);
	private HandlerInfo handlerInfo;

	private static final String REQUEST_HEADER_NAMESPACE_PREFIX = "typ";
	private String requestHeaderNamespace = "http://xml.comcast.com/types";;

	public String getRequestHeaderNamespace() {
		return requestHeaderNamespace;
	}

	public void setRequestHeaderNamespace(String requestHeaderNamespace) {
		this.requestHeaderNamespace = requestHeaderNamespace;
	}

	public void init(HandlerInfo hi) {
		this.handlerInfo = hi;
		String namespace = (String) this.handlerInfo.getHandlerConfig().get(REQUEST_HEADER_NS_KEY);
		if (namespace != null) {
			this.requestHeaderNamespace = namespace;
		}

	}

	protected boolean addServiceContextToHeader(MessageContext context, String headerType) {
		SOAPMessageContext messageContext = (SOAPMessageContext) context;
		try {
			SOAPHeader header = messageContext.getMessage().getSOAPPart().getEnvelope().getHeader();
			ServiceContext serviceContext = ServiceContextHandler.getInstance().getServiceContext();

			String headerNamespace = "http://xml.comcast.com/types";//(String) this.handlerInfo.getHandlerConfig().get(REQUEST_HEADER_NS_KEY);
			
/*			if(logger.isDebugEnabled())
				logger.debug(REQUEST_HEADER_NAMESPACE_PREFIX+ " : headerNamespace: " + headerNamespace);
			if(serviceContext != null) {
				logger.debug(SOURCE_SYSTEM_ID+ ": "+ serviceContext.getSourceSystemId());
				logger.debug(USER_ID + " : "+ serviceContext.getUserId());
				logger.debug(SOURCE_SERVER_ID+ " : " + serviceContext.getSourceServerId());
				logger.debug(TRACKING_ID + " : "+  serviceContext.getTrackingId());
			}*/
			
			if (headerNamespace == null) {
				headerNamespace = serviceContext.getNamespace();
			}

			SOAPElement hdr = header.addChildElement(headerType,REQUEST_HEADER_NAMESPACE_PREFIX, headerNamespace);
			addChildElement(hdr, TIMESTAMP, this.createDateTime());
			if (REQUEST_HEADER.equals(headerType)) {
				addChildElement(hdr, SOURCE_SYSTEM_ID, serviceContext.getSourceSystemId());
				addChildElement(hdr, USER_ID, serviceContext.getUserId());
				addChildElement(hdr, SOURCE_SERVER_ID, serviceContext.getSourceServerId());
			}
			//addChildElement(hdr, TRACKING_ID, serviceContext.getTrackingId());
			addChildElement(hdr, TRACKING_ID, MDC.get("trackingId"));
		} catch (SOAPException e) {
			logger.warn("Error processing soap header", e);
		}

		return true;
	}
	
	 protected boolean addWsaHeader(MessageContext context){
	    	SOAPMessageContext messageContext = (SOAPMessageContext) context;
	    	try {
	    		ServiceContext serviceContext = ServiceContextHandler.getInstance().getServiceContext();
	    		// only add the wsa header when specified
	        	Boolean addWsaHeader = serviceContext.getAddWsaHeader();
	    		if (!addWsaHeader){
	    			return false;
	    		}
	        	
	    		// pull the original message id from the context and set the wsa relates to header
	        	String relatesTo = serviceContext.getWsaMessageId();
	        	String action = serviceContext.getWsaAction();
	        	
	        	if (relatesTo != null && 
	        			!relatesTo.equals("")) {
	        		
	        		SOAPHeader header = messageContext.getMessage().getSOAPPart().getEnvelope().getHeader();
	        		SOAPElement wsaAction = header.addChildElement(WSA_ACTION, WS_ADDRESSING_PREFIX, WS_ADDRESSING_NAMESPACE);
	        		wsaAction.setValue(action);
	        		SOAPElement wsaRelatesTo = header.addChildElement(WSA_RELATES_TO, WS_ADDRESSING_PREFIX, WS_ADDRESSING_NAMESPACE);
		        	wsaRelatesTo.setValue(relatesTo);

	        	}

	    	} catch (SOAPException e) {
	    		logger.warn("Error adding WS-Addressing Header to SOAP header", e);
	    	}
	    	
	    	return true;
	    }
	
	 private String createDateTime() {
	        return DateUtils.getISO8601DateTime(new java.util.Date());
	    }

	private void addChildElement(SOAPElement elem, String name, Object value) throws SOAPException {
		if (value != null) {
			SOAPElement node = elem.addChildElement(name,REQUEST_HEADER_NAMESPACE_PREFIX);
			node.addTextNode(value.toString());
		}
	}

	public QName[] getHeaders() {
		return handlerInfo.getHeaders();
	}
	
	public HandlerInfo getHandlerInfo(){
    	return this.handlerInfo;
    }

}